<?php
// +----------------------------------------------------------------------
// | User: zq
// +----------------------------------------------------------------------
// | Time: 2021/12/1 09:59
// +----------------------------------------------------------------------

namespace App\Services\Order;

use App\CodeResponse;
use App\Exceptions\BusinessException;
use App\Models\Goods\Goods;
use App\Models\Goods\GoodsProduct;
use App\Models\Order\Cart;
use App\Services\BaseService;
use App\Services\Goods\GoodsService;
use App\Services\Promotion\GrouponService;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;

class CartService extends BaseService
{
    /**
     * 购物车列表
     * @param $userId
     * @return Cart[]|Builder[]|Collection
     */
    public function getCartList($userId)
    {
        return Cart::query()->where('user_id', $userId)->get();
    }

    // 获取选中的购物车列表
    public function getCheckedCarts($userId)
    {
        return Cart::query()->where('user_id', $userId)
            ->where('checked', 1)
            ->get();
    }

    /**
     * 获取已选择的购物车列表
     * @param $userId
     * @param $cartId
     * @return Cart[]|Builder[]|Collection|Collection[]
     */
    public function getCheckedCartlist($userId, $cartId = null)
    {
        if (empty($cartId)) {
            $checkedGoodsList = $this->getCheckedCarts($userId);
        } else {
            $cart = $this->getCartById($userId, $cartId);
            if (empty($cart)) {
                $this->throwBadArgumentValue();
            }
            $checkedGoodsList = collect([$cart]);
        }
        return $checkedGoodsList;
    }

    // 减去团购优惠
    public function getCartPriceCutGroupon($checkedGoodsList, $grouponRulesId, &$grouponPrice)
    {
        $grouponRules = GrouponService::getInstance()->getGrouponRulesById($grouponRulesId);
        $checkedGoodsPrice = 0; //所有商品的总金额
        foreach ($checkedGoodsList as $cart) {
            if ($grouponRules && $grouponRules->goods_id == $cart->goods_id) {
                $grouponPrice = bcmul($grouponRules->discount, $cart->number, 2);
                $price = bcsub($cart->price, $grouponRules->discount, 2);
            } else {
                $price = $cart->price;
            }
            $price = bcmul($price, $cart->number, 2);
            $checkedGoodsPrice = bcadd($checkedGoodsPrice, $price, 2);
        }

        return $checkedGoodsPrice;
    }

    /**
     * 获取有效的购物车列表
     * @param $userId
     * @return Collection|Cart[]
     */
    public function getValidCartList($userId)
    {
        $list = $this->getCartList($userId);
        $goodsIds = $list->pluck('goods_id')->toArray();
        $goodsList = GoodsService::getInstance()->getGoodsListByIds($goodsIds)->keyBy('id');
        $invalidCartIds = [];
        $list = $list->filter(function (Cart $cart) use ($goodsList, &$invalidCartIds) {
            /** @var Goods $goods */
            $goods = $goodsList->get($cart->goods_id);
            $isValid = !empty($goods) && $goods->is_on_sale;
            if (!$isValid) {
                $invalidCartIds[] = $cart->id;
            }
            return $isValid;
        });
        $this->deleteCartList($invalidCartIds);
        return $list;
    }

    // 批量删除购物车物品
    public function deleteCartList($ids)
    {
        if (empty($ids)) {
            return 0;
        }
        Cart::query()->whereIn('id', $ids)->delete();
    }

    public function getCartById($userId, $id, $columns = ['*'])
    {
        return Cart::query()->where('user_id', $userId)->where('id', $id)->first($columns);
    }

    public function getCartProduct($userId, $goodsId, $productId)
    {
        return Cart::query()->where('user_id', $userId)
            ->where('goods_id', $goodsId)
            ->where('product_id', $productId)
            ->first();
    }

    /**
     * @param $goodsId
     * @param $productId
     * @return array
     * @throws BusinessException
     */
    public function getGoodsInfo($goodsId, $productId)
    {
        // 查看商品是否可以购买(存在或下架)
        $goods = GoodsService::getInstance()->getGoods($goodsId);
        if (is_null($goods) || !$goods->is_on_sale) {
            $this->throwBusinessException(CodeResponse::GOODS_UNSHELVE);
        }

        // 判断购物车是否存在相同的货品
        $product = GoodsService::getInstance()->getGoodsProductById($productId);
        if (is_null($product)) {
            $this->throwBusinessException(CodeResponse::GOODS_NO_STOCK);
        }

        return [$goods, $product];
    }

    /**
     * 添加购物车
     * @param $userId
     * @param $goodsId
     * @param $productId
     * @param $number
     * @return Cart
     * @throws BusinessException
     */
    public function add($userId, $goodsId, $productId, $number)
    {
        list($goods, $product) = $this->getGoodsInfo($goodsId, $productId);
        $cartProduct = $this->getCartProduct($userId, $goodsId, $productId);
        if (is_null($cartProduct)) {
            return $this->newCart($userId, $goods, $product, $number);
        } else {
            $number = $cartProduct->number + $number;
            return $this->editCart($cartProduct, $product, $number);
        }
    }

    /**
     * @param $userId
     * @param $goodsId
     * @param $productId
     * @param $number
     * @return Cart
     * @throws BusinessException
     */
    public function fastadd($userId, $goodsId, $productId, $number)
    {
        list($goods, $product) = $this->getGoodsInfo($goodsId, $productId);
        $cartProduct = $this->getCartProduct($userId, $goodsId, $productId);
        if (is_null($cartProduct)) {
            return $this->newCart($userId, $goods, $product, $number);
        } else {
            return $this->editCart($cartProduct, $product, $number);
        }
    }

    /**
     * @param  Cart  $exisCart
     * @param  GoodsProduct  $product
     * @param  int  $number
     * @return Cart
     * @throws BusinessException
     */
    public function editCart($exisCart, $product, $num)
    {
        // edit cart product number
        // 判断数量是否大于库存
        if ($num > $product->number) {
            $this->throwBusinessException(CodeResponse::GOODS_NO_STOCK);
        }
        $exisCart->number = $num;
        $exisCart->save();
        return $exisCart;
    }

    public function countCartProduct($userId)
    {
        return Cart::query()->where('user_id', $userId)->sum('number');
    }

    public function newCart($userId, Goods $goods, GoodsProduct $product, $number)
    {
        // 判断数量是否大于库存
        if ($number > $product->number) {
            $this->throwBusinessException(CodeResponse::GOODS_NO_STOCK);
        }
        $cart = Cart::new();
        $cart->goods_sn = $goods->goods_sn;
        $cart->goods_name = $goods->name;
        $cart->pic_url = $product->url ?: $goods->pic_url;
        $cart->price = $product->price;
        $cart->specifications = $product->specifications;
        $cart->user_id = $userId;
        $cart->checked = true;
        $cart->number = $number;
        $cart->goods_id = $goods->id;
        $cart->product_id = $product->id;
        $cart->save();
        return $cart;
    }

    public function delete($userId, $productIds)
    {
        return Cart::query()->where('user_id', $userId)->whereIn('product_id', $productIds)->delete();
    }

    public function updateChecked($userId, $productIds, $isChecked)
    {
        return Cart::query()->where('user_id', $userId)
            ->whereIn('product_id', $productIds)
            ->update(['checked' => $isChecked]);
    }

    public function clearCartGoods($userId, $cartId = null)
    {
        if (empty($cartId)) {
            return Cart::query()->where('user_id', $userId)->where('checked', 1)->delete();
        }
        return Cart::query()->where('user_id', $userId)->where('id', $cartId)->delete();
    }
}